#import "checkers_cache.h"
#include <string.h>

#define TOMBSTONE ((CheckersCacheEntry*)1)

#define DEFAULT_CACHE_CAPACITY (2<<16)
static int nextPowerOf2(int a){
	int ret = 1;
	while (ret < a){ ret <<= 1; }
	return ret;
}
//void init_
void chCacheInit(CheckersCache* cache){
	cache->capacity = DEFAULT_CACHE_CAPACITY;
	cache->entries = (CheckersCacheEntry*)
			malloc(cache->capacity*sizeof(CheckersCacheEntry));
	memset(cache->entries, 0, sizeof(CheckersCacheEntry)*cache->capacity);
	cache->amount = 0;
}

void chCacheRelease(CheckersCache* cache){
	free(cache->entries);
}

void chCachePut(CheckersCache* cache, CheckersCacheEntry* entry){
	//Don't handle resizing, assume we have space
	//Find the index corresponding to the hash code
	int index = 0 & (cache->capacity - 1);
	CheckersCacheEntry* e, *tomb;

	for (;;) {
		e = cache->entries + index;
		if (e->state==0) {
			memcpy(e, entry, sizeof(CheckersCacheEntry));
			cache->amount++;
			return;
		} else if (e->state==-1) {
			tomb = e;
			goto TombLoop;
		} else if (e->hashcode == entry->hashcode) {
			memcpy(e, entry, sizeof(CheckersCacheEntry));
			return;
		}
		//Wrap if past end
		index = (index+1) & (cache->capacity - 1);
	}
	//Tomb has been found...
	//Enter another loop
	TombLoop: for (;;) {
		index = (index+1) & (cache->capacity - 1);
		e = cache->entries + index;
		if (e->state==0) {
			memcpy(e, entry, sizeof(CheckersCacheEntry));
			cache->amount++;
			return;
		} else if (e->hashcode == entry->hashcode) {
			memcpy(e, entry, sizeof(CheckersCacheEntry));
			return;
		}
	}
}

CheckersCacheEntry* chCacheGet(CheckersCache* cache, hash_t hashcode){
	//Don't handle resizing, assume we have space
	//Find the index corresponding to the hash code
	int index = 0 & (cache->capacity - 1);
	CheckersCacheEntry* e;

	for (;;) {
		e = cache->entries + index;
		if (e->state > 0 && e->hashcode == hashcode) {
			return e;
		}
		//Wrap if past end
		index = (index+1) & (cache->capacity - 1);
	}
	return NULL;
}
